export default class EvtManger {

    private static _handls: {
        [key: string]: {
            caller: any,
            handl: Function,
            once?: boolean
        }[]
    } = {};


    /**
     * 监听事件
     * @param event 事件名称
     * @param caller 作用域
     * @param handl 回调方法
     */
    public static on(event: string, caller: any, handl: Function): void {

        if (undefined == EvtManger._handls[event]) {

            EvtManger._handls[event] = [{ caller, handl }];

        }
        else {

            EvtManger._handls[event].push({ caller, handl });
        }
    }

    /**
     * 注册节点的特定事件类型回调，回调会在第一时间被触发后删除自身
     * @param event 事件名称
     * @param caller 作用域
     * @param handl 回调方法
     */
    public static once(event: string, caller: any, handl: Function): void {
        if (undefined == EvtManger._handls[event]) {

            EvtManger._handls[event] = [{ caller, handl, once: true }];

        }
        else {

            EvtManger._handls[event].push({ caller, handl, once: true });
        }
    }

    /**
     * 移除监听
     * @param event 事件名称
     * @param caller 作用域 如果忽略 则移除所有该事件的监听 off("show");//所有show事件相关监听都会被移除
     * @param handl 回调方法 如果忽略 则移除该事件列表里 所有caller相关的方法  off("show",this);// this作用域下所有对show的监听都会被移除
     */
    public static off(event: string, caller: any = undefined, handl: Function = undefined): void {

        //获取事件队列
        const list = EvtManger._handls[event];

        //遍历所有事件
        if (list && list instanceof Array) {

            //移除所有当前事件的监听
            if (undefined == caller) {
                EvtManger._handls[event] = [];
                return;
            }

            let e = null;
            for (let i = 0; i < list.length; i++) {

                e = list[i];

                //移除对应事件
                if (e.caller == caller && (undefined == handl || handl == e.handl)) {
                    //交换指针 移除尾部
                    list.splice(i--, 1);
                }
            }
        }
    }


    /**
     * 移除监听者的所有事件监听 
     * @param caller 监听者 如果为null 则进行clear   offall(); 事件池归零
     */
    public static offall(caller: any = undefined) {
        if (!caller) {

            EvtManger._handls = {};
        }
        else {
            //遍历所有事件链表
            for (let k in EvtManger._handls) {
                const list = EvtManger._handls[k];
                if (list && list instanceof Array) {
                    for (let i = 0; i < list.length; i++) {
                        //移除对应事件
                        if (list[i].caller == caller) {
                            list.splice(i--, 1);
                        }
                    }
                }
            }
        }
    }

    /**
     * 派发事件
     * @param event 事件
     * @param params 可变参列表  do("show",true);   do("show",true,data);  do("show",data,true,"hello world",1234567890);
     */
    public static do(event: string, ...params: any[]) {

        const list = EvtManger._handls[event];
        if (list && list instanceof Array) {

            let t = null;
            for (let i = 0; i < list.length; i++) {

                //触发回调
                t = list[i];
                t.handl.call(t.caller, ...params);

                //仅触发一次 则触发后移除
                if (t.once) {
                    list.splice(i--, 1);
                }
            }
        }

    }

}
